#ifndef B4D8F49B_C91D_4B7C_8989_CDBA89A847D9
#define B4D8F49B_C91D_4B7C_8989_CDBA89A847D9

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <sstream>
#include <sys/stat.h>
#include <sys/sendfile.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <algorithm>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdarg.h>

#include "ExitData.h"


#define LINE_END "\r\n"
#define Heaser_Sep ": "
#define HTTP_VERSION "HTTP/1.0"
#define WEBWOOT "wwwroot"
// #define HOME_PAGE "index.html"
#define HOME_PAGE "index.html"
#define PAGE_404 "404.html"
#define PAGE_ENROLL "enroll.html"
#define PAGE_FUNCTIONS "functions/linux_web_inter.html"

// 状态码描述
static std::string codeToDesc(int code)
{
    std::string code_desc;
    switch(code)
    {
    case 200:
        code_desc = "OK";
        break;
    case 400:
        code_desc = "BAD_QUEST";
        break;
    case 404:
        code_desc = "NOT_FOUND";
        break;
    default:
        code_desc = "NONE";
        break;
    }
    return code_desc;
}
// url 后缀 匹配（描述）
static std::string suffixToDesc(const std::string& my_suffix)
{
    static std::unordered_map<std::string, std::string> suffix_to_desc = {
        {".html", "text/html"},
        {".js", "application/javascript"},
        {".jpg", "application/x-jpg"},
        {".css", "text/css"},
        {".xml", "application/xml"}
    };
    auto iter = suffix_to_desc.find(my_suffix);
    if(iter != suffix_to_desc.end())
    {
        return iter->second;
    }
    return "text/html";
}

// http请求
// 请求——发送数据给子进程
// 响应——接受子进程发来的数据
class HttpRequest
{
public:
    HttpRequest():header_content_length(0),cgi(false)
    {}
    ~HttpRequest(){}
public:
    // 请求肯定包含：请求行 && 请求报头 && 空行 && 请求正文
    // 之后解析，解析完毕包含有：各类相应的字段
    // 最后判断访问的是什么资源（静态资源 or 动态资源(cgi机制)）
    std::string request_line;                   // 1.请求行
    std::vector<std::string> request_header;    // 2.请求报头
    std::string blank;                          // 3.空行
    std::string request_body;                   // 4.请求正文

    // 解析之后的相关字段
    // 请求行 = 请求方法(POST/GET) + 请求的url地址 + 请求的HTTP版本(http/1.0)
    // 请求报头 = 各个key-value的字段
    // a.请求行
    std::string line_method;     // POST/GET
    std::string line_url;        // url地址
    std::string line_http_version;   // 请求的http版本、
    // a.1 对 url 做下特别处理
    std::string url_path;    // url中的属性：请求地址url的path字段（http资源的地址），判断访问哪一个资源
    std::string url_query_string;    // url中的属性：请求地址url的query_string字段【有“资源的地址”了，如何访问。eg:a=100&b=200】
    std::string url_suffix;      // 请求资源 url 的后缀（.html or .jpg or .css or .xml）

    // b.请求报头
    std::unordered_map<std::string, std::string> header_kv;
    int header_content_length;  // 请求报头中的属性：用来描述正文的字节大小

    // 最后判断访问的是什么资源（静态资源 or 动态资源(cgi机制)）
    bool cgi;   // 是否执行 cgi 机制
    int size;   // 请求资源大小
};

// http响应
class HttpResponse
{
public:
    HttpResponse():status_line_code(OK), response_fd(-1),response_blank(LINE_END)
    {}
    ~HttpResponse(){}
public:
    // 响应包含四部分：状态行 && 响应报头 && 空行 && 相应正文
    std::string response_status_line;           // 响应状态行
    std::vector<std::string> response_header;   // 响应报头
    std::string response_blank;                 // 响应空行
    std::string response_body;                  // 响应正文
    
    // 除此之外，还有一些补充的其他信息：状态码 && 向哪一个“文件”内发送我们的响应（接受响应信息）
    int status_line_code;   // 响应状态码
    int response_fd;            // 接受响应信息文件描述符
};

// 开始通过 EndPoint 类进行通信
class EndPoint
{
private:
    // http发送方和 http 响应方 通过 sock 交互（主）
    int sock_fd;   // 套接字
    HttpRequest http_request;   // http 请求服务（获取并解析请求）
    HttpResponse http_response; // http 响应服务（构建并发送响应）
    // 判断 http 服务器是否正在运行处理数据（次）
    bool is_stop;   
public:
    EndPoint(int sockfd):sock_fd(sockfd),is_stop(false)
    {}
    ~EndPoint()
    {
        close(sock_fd);
    }
private:    
    // 请求
    // 1.读取——读取请求行 和 请求报头
    bool recvHttpRequestLine();
    bool recvHttpRequestHeader();
    // 2.解析——解析请求行 和 请求报头
    void parseHttpRequestLine();
    void parseHttpRequestHeader();
    // 3.读取——读取请求正文
    bool recvHttpRequestBody();
private:
    // 响应
    // 1. 执行 cgi 机制的资源
    int processCgi();
    // 2. 执行 静态网页 的资源
    int processNonCgi();
    // 3. 构建正常的响应报文
    void buildOkResponse(std::string index_page);
    // 4. 构建异常的响应报文
    void buildErrorResponse(std::string error_page);
    // 5. 构建响应——响应填充
    void buildHttpResponseHelper();
public:
    // 健壮处理
    // 1.http服务器是否运行
    bool isStop();
    // 2.识别并处理请求
    void recvHttpRequest();
    // 3.构建响应
    void buildHttpResponse();
    // 4.发送响应
    void sendHttpResponse();
};

// 回调类（函数）
// #define DEBUG_ 1
class CallBack
{
public:
    // static 修饰的唯一的一个函数
    static void handlerRequest(int sock_fd)
    {
        std::cout << "<----- 你成功的进入了 HTTP 服务器，可以开始运行了 ----->" << std::endl;
        // lg(INFO, "handlerRequest Begin....");
#ifdef DEBUG_
        char buffer[4096]= {0};
        recv(sock, buffer, sizeof(buffer), 0);
        std::cout << buffer << std::endl;
#else  
        // 开始执行 Http 服务
        EndPoint* ep = new EndPoint(sock_fd);
        ep->recvHttpRequest();
        if(!ep->isStop())
        {
            // lg(INFO, "Recv success, Begin build and send....");
            std::cout << "Recv success, Begin build and send...." << std::endl;
            ep->buildHttpResponse();
            ep->sendHttpResponse();
        }
        else
        {
            std::cout << "Recv Error, Stop build and send...." << std::endl;
            // lg(WARN, "Recv Error, Stop build and send....");
        }
        delete ep;
#endif
        close(sock_fd);
        std::cout << "handlerRequest End...." << std::endl;
        // lg(INFO, "handlerRequest End....");
    }
public:
    CallBack()
    {}
    ~CallBack()
    {}
    void operator()(int sock)
    {
        handlerRequest(sock);
    }
};


#endif /* B4D8F49B_C91D_4B7C_8989_CDBA89A847D9 */
